﻿using FireChat.Server.Session.Receiver;
using FireChat.Share.Database.Util;
using FireChat.Server.Session.Remote;
using FireChat.Share.HTTP.Model;
using FireChat.Server.Database.Table.Accounts;
using FireChat.Share.Web.Package;
using FireChat.Share.Web.Model.Query.Account;

namespace FireChat.Server.Database.Manager;


/// <summary>
/// 账户令牌管理
/// </summary>
internal static class AccountManager
{
    #region --Token--


    /// <summary>
    /// 所有已登录用户
    /// </summary>
    private static readonly List<RemoteSession> _sessions = new();

    /// <summary>
    /// 所有在线远程连接
    /// </summary>
    public static IEnumerable<RemoteSession> LoginAccountSession => _sessions;



    /// <summary>
    /// 创建会话信息
    /// </summary>
    public static bool RegisterAccountToken(this RemoteSession session, int uid)
    {
        if (_sessions.Find(x => x.AccountToken.UID == uid) != null)
        {
            return false;
        }

        if (session.VerifyAccountToken())
        {
            return false;
        }

        session.AccountToken = new()
        {
            UID = uid,
            Value = Guid.NewGuid().ToString()
        };

        _sessions.Add(session);

        return true;
    }

    /// <summary>
    /// 删除会话信息
    /// </summary>
    public static bool DeleteAccountToken(this RemoteSession session)
    {
        var token = session.AccountToken;
        if (token is null) return false;

        var result = _sessions.RemoveAll(x => x.AccountToken.UID == token.UID && x.AccountToken.Value == token.Value);
        session.AccountToken = AccountToken.None;

        return result > 0;
    }

    /// <summary>
    /// 验证远程客户端 不存在则回复客户端指定消息
    /// </summary>
    /// <param name="message">回应消息</param>
    public static bool VerifyAccountToken(this RemoteSession session)
    {
        if (session.AccountToken == AccountToken.None)
        {
            return false;
        }

        var info = _sessions.Find(x => x.AccountToken == session.AccountToken);
        if (info is null) return false;

        return true;
    }


    #endregion


    #region --Account--


    /// <summary>
    /// 获取账户UID
    /// </summary>
    public static int GetAccountID(this RemoteSession session)
    {
        return session.AccountToken.UID;
    }

    /// <summary>
    /// 获取账户信息
    /// </summary>
    public static AccountData? GetInstance(Func<AccountData, bool> matcher)
    {
        return DataTableManager<AccountData>.Select(matcher).FirstOrDefault();
    }

    /// <summary>
    /// 获取账户信息用用户名
    /// </summary>
    public static AccountData? GetInstanceByName(string username)
    {
        return GetInstance(x => x.Username.ToLower() == username.ToLower());
    }


    /// <summary>
    /// 登录账户
    /// </summary>
    public static ServerPackage Login(this PackageReceiver receiver, LoginQuery query)
    {
        if (GetInstanceByName(query.Username) is not AccountData account)
        {
            return receiver.ReplyFailureAsync("账号不存在");
        }

        if (query.Password == account.Password)
        {
            receiver.Session.RegisterAccountToken(account.Id);
            return receiver.ReplySuccessAsync("登录成功", receiver.Session.AccountToken);
        }

        return receiver.ReplyFailureAsync("密码错误!");
    }

    /// <summary>
    /// 注册账户
    /// </summary>
    public static ServerPackage Register(this PackageReceiver receiver, RegisterQuery query)
    {
        if (GetInstanceByName(query.Username) is not null)
        {
            return receiver.ReplyFailureAsync("无法注册, 账号已存在!");
        }

        AccountData database_account = new()
        {
            Email = "",
            Username = query.Username,
            Password = query.Password
        };

        var count = DataTableManager<AccountData>.Insert(database_account);
        if (count <= 0)
        {
            return receiver.ReplyFailureAsync("注册失败, 无法写入数据库!");
        }

        return receiver.ReplySuccessAsync("注册成功");
    }

    /// <summary>
    /// 退出账户登录
    /// </summary>
    public static ServerPackage Logout(this PackageReceiver receiver)
    {
        if (receiver.Session.DeleteAccountToken())
        {
            return receiver.ReplySuccessAsync("账号已退出");
        }

        return receiver.ReplyFailureAsync("账号未登录");
    }


    #endregion
}